package com.xinmao.quantitative.trad.strategies.grid;

import com.xinmao.quantitative.FundTrade;
import com.xinmao.quantitative.enums.GridTansType;
import com.xinmao.quantitative.model.GridModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.ta4j.core.Bar;
import org.ta4j.core.BarSeries;
import org.ta4j.core.Trade;
import org.ta4j.core.analysis.cost.CostModel;
import org.ta4j.core.num.DecimalNum;
import org.ta4j.core.num.Num;

import java.math.BigDecimal;
import java.util.*;

@Slf4j
@Service
public class GridTradingStrategy2 {

    public List<Trade> getTradeByPrice(GridModel gridModel,BarSeries series){
        //计算进入价格
        Num entryPrice = gridModel.getEnterPrice();
        if(gridModel.getEnterPrice() == null){
            entryPrice = gridModel.getUpPrice().minus(gridModel.getLowPrice()).dividedBy(DecimalNum.valueOf(2)).plus(gridModel.getLowPrice());
        }
        List<Trade> trades = new ArrayList<>();
        //最大持仓数量
        if(gridModel.getMaxHoldNum() == null){
            Num maxHoldNum = gridModel.getUpPrice().minus(gridModel.getLowPrice()).dividedBy(gridModel.getByAmount()).dividedBy(DecimalNum.valueOf(2));
            gridModel.setMaxHoldNum(gridModel.getBuyNum().multipliedBy(DecimalNum.valueOf(maxHoldNum.intValue())));
        }
        Num currentHold = series.zero();
        for (int i = 0; i < series.getBarCount(); i++) {
            Num currentPrice = series.getBar(i).getClosePrice();
            Num multiple = DecimalNum.valueOf(currentPrice.minus(entryPrice).dividedBy(gridModel.getByAmount()).intValue());
            //价格下跌到买点
            //1：下跌是否大于等于一格
            //2：当前持仓是否小于最大持仓
            if (multiple.isLessThanOrEqual(DecimalNum.valueOf(-1)) && gridModel.getMaxHoldNum().minus(currentHold).isGreaterThan(series.zero())){
                List<Trade> buyTrade = openPosition(series.getBar(i), multiple, i, gridModel.getCostModel(), gridModel.getBuyNum());
                //当前信号开仓数量
                for (Trade trade : buyTrade){
                    if(currentHold.plus(trade.getAmount()).isLessThanOrEqual(gridModel.getMaxHoldNum())){
                        trades.add(trade);
                        currentHold = currentHold.plus(trade.getAmount());
                    }
                    //变更进入价格
                    entryPrice  = currentPrice;
                }
            }
            //价格上涨到卖点
            //1：上涨是否大于等于一格
            //2：当前持仓是否大于0
            if(multiple.isGreaterThanOrEqual(series.one()) && currentHold.isGreaterThan(series.zero())){
                List<Trade> sellTrade = closePosition(series.getBar(i), multiple, i, gridModel.getCostModel(), gridModel.getBuyNum());
                //当前平仓信号数量
                for (Trade trade : sellTrade){
                    if(currentHold.minus(trade.getAmount()).isGreaterThanOrEqual(series.zero())){
                        trades.add(trade);
                        currentHold = currentHold.minus(trade.getAmount());
                    }
                    //变更进入价格
                    entryPrice  = currentPrice;
                }
            }
        }
        return trades;
    }

    /**
     * 开仓逻辑
     */
    private List<Trade> openPosition(Bar bar, Num multiple, int index, CostModel costModel, Num byNum) {
        int mt = multiple.intValue();
        List<Trade> trades = new ArrayList<>();
        while(mt < 0){
            trades.add(new FundTrade(index, Trade.TradeType.BUY, bar.getClosePrice(), byNum, costModel));
            mt++;
        }
        return trades;
    }

    /**
     * 平仓逻辑
     */
    private List<Trade> closePosition(Bar bar, Num multiple, int index, CostModel costModel, Num byNum) {
        int mt = multiple.intValue();
        List<Trade> trades = new ArrayList<>();
        while(mt > 0){
            trades.add(new FundTrade(index, Trade.TradeType.SELL, bar.getClosePrice(), byNum, costModel));
            mt--;
        }
        return trades;
    }
}